package com.glodon.zhuanli.front;

import com.glodon.framework.common.shiro.exception.InvalidUserAuthenticationException;
import com.glodon.framework.common.util.JsonMapper;
import com.glodon.zhuanli.system.entity.SysUser;
import com.glodon.zhuanli.system.service.SysUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;

@Slf4j
public class ZLUserRealm extends AuthorizingRealm implements InitializingBean{

	@Autowired
	private SysUserService sysUserService ;

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		//记录在认证过程中出现的异常信息
		AuthenticationException authenticationException = null ;
		//记录认证实体
		SysUser sysUser = null ;
		try {
			sysUser = getUserByToken(token) ;
			//对用户信息进行校验
			if(sysUser==null){
				//已存在账号的密码错误
				throw new IncorrectCredentialsException() ;
			}else if( sysUser.getStatus()!=null && ! StringUtils.equalsIgnoreCase( sysUser.getStatus() , "user_status_valid" ) ){
				//用户状态不等于 user_status_valid
				log.info(sysUser.getCode()+" , 用户状态: "+(sysUser.getStatus()==null?"用户状态为空":sysUser.getStatus()));
				//判断账号是否有效
				throw new InvalidUserAuthenticationException() ;
			}
		} catch (Exception e) {
			//捕获在获取用户信息过程中出现的异常信息
			if(e instanceof AuthenticationException){
				authenticationException = (AuthenticationException)e ;
			}else{
				authenticationException = new AuthenticationException(e.getMessage()) ;
			}
		}
		//如果获取用户异常，抛出异常信息，并存储在session中
		if(authenticationException!=null){
			log.warn("认证异常："+authenticationException.getClass().getName()+" , message:"+authenticationException.getMessage());
			//session中存储的认证异常的key为AuthenticationException类名称
			SecurityUtils.getSubject().getSession().setAttribute(AuthenticationException.class.getName() , authenticationException);

			throw authenticationException ;
		}

		//认证成功之后返回认证信息
		SimpleAuthenticationInfo authenticationInfo =
				new SimpleAuthenticationInfo( sysUser , token.getCredentials() , getName()) ;

		return authenticationInfo ;
	}

	/**
	 * 进行授权
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo() ;

		return authorizationInfo ;
	}
	
	/**
	 * 用户权限信息认证，可以在用户认证通过后对用户进行授权，避免二次访问
	 */
	protected SysUser getUserByToken(AuthenticationToken token) throws Exception {
		SysUser sysUser = null ;
		
		UsernamePasswordToken userToken = (UsernamePasswordToken)token ;
		
		log.info("验证登陆信息->"+JsonMapper.toJSONString(userToken , true));
		
		if(StringUtils.isNotBlank(userToken.getUsername()) && userToken.getPassword()!=null &&
				StringUtils.isNotBlank(String.valueOf(userToken.getPassword()))){
			//判断用户名是否存在
			boolean isExistUser = sysUserService.existUserCode(userToken.getUsername().trim()) ;
			if(isExistUser){
				//进行实体登陆验证，如果存在账号，返回登陆之后的实体信息
				sysUser = sysUserService.login( userToken.getUsername() , String.valueOf(userToken.getPassword()) ) ;
			}else{
				//如果账号不存在，抛出未知账号的异常
				throw new UnknownAccountException() ;
			}
		}
		
		return sysUser ;
	}

	@Override
	public void afterPropertiesSet() throws Exception {
		setAuthenticationTokenClass(UsernamePasswordToken.class);
	}
	
}
